<html>
<head><meta charset="utf-8"><title>Default for arrays via const generics · t-lang · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/index.html">t-lang</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html">Default for arrays via const generics</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="204289821"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204289821" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204289821">(Jul 18 2020 at 07:47)</a>:</h4>
<p>MikailBag (who might be <span class="user-mention" data-user-id="223584">@Mikail Bagishov</span> on zulip, not sure) opened <a href="https://github.com/rust-lang/rust/issues/74254">#74254</a> recently. This PR implements <code>Default</code> for arrays using const generics. I am confident in the implementation and think the we can use this after some doc/naming improvements and some more tests.</p>
<p>Unlike the traits implemented in <a href="https://github.com/rust-lang/rust/issues/74060">#74060</a>, <code>Default</code> is also implemented for <code>[T; 0]</code>, even if <code>T</code> does not implement <code>Default</code> itself, which means we can't just use <code>impl&lt;T, const N: usize&gt; Default for [T; N]</code>.</p>



<a name="204289822"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204289822" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204289822">(Jul 18 2020 at 07:47)</a>:</h4>
<p>There are 3 ways we can proceed here.</p>
<ol>
<li>keep using the old manual impls</li>
<li>use the new impls with a <code>LengthAtMost32</code> bound</li>
<li>do not restrict the default impls, remove the bound on <code>Default</code> at the same time as <a href="https://github.com/rust-lang/rust/issues/74060">#74060</a> (in the same stable release)</li>
</ol>



<a name="204289826"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204289826" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204289826">(Jul 18 2020 at 07:47)</a>:</h4>
<p>First of all, I <em>strongly</em> believe 2 is better than 1. Using const generics here results in better error messages, <a href="https://perf.rust-lang.org/compare.html?start=c2dbebd3d4ad21e80ef4e7535dd1e868aaad7e50&amp;end=fdf2a2df58d771b9afde026fa1c894dfd15e138e">slightly faster compile times</a>(not really...  it seems like it's most <code>cargo doc</code>which got faster) and cleaner docs.</p>
<p>We do not perfectly optimize the use of <code>MaybeUninit::assume_init</code> here though,<br>
which results in slightly worse codegen for types with <code>T::default() != mem::zeroed()</code>, which imo will most probably not be noticeable.</p>



<a name="204289868"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204289868" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204289868">(Jul 18 2020 at 07:48)</a>:</h4>
<p>Now, about 3. This PR uses <code>#![feature(marker_trait_attrs, const_generics, min_specialization)]</code>, meaning that doing this implicitly guarantees that we will always have some version of this in the standard library.</p>
<p>I am personally <em>slightly</em> in favor of not restricting <code>Default</code> to <code>ArrayLenAtMost32</code>.</p>



<a name="204289877"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204289877" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204289877">(Jul 18 2020 at 07:48)</a>:</h4>
<p>It looks like <code>marker_trait_attrs</code> is fairly close to stabilization,<br>
see <a href="https://github.com/rust-lang/rust/issues/29864#issuecomment-660323818">#29864(comment)</a> and <code>min_specialization</code> is already very prevalent inside of std for performance reasons, which makes me believe that it will be very unlikely that we want/can remove these features without also having a working replacement for the <code>Default</code> impls.</p>



<a name="204289882"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204289882" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204289882">(Jul 18 2020 at 07:48)</a>:</h4>
<p>Even if <code>min_specialization</code> or <code>marker_trait_attrs</code> end up getting removed, we can still keep this implementation by changing <code>Default</code> to a <code>#[lang_item]</code> and adding a builtin impl for <code>[T; 0]</code>. (not completely sure how easy this would be, if required, I can try and create a proof of concept here)</p>



<a name="204289892"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204289892" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204289892">(Jul 18 2020 at 07:49)</a>:</h4>
<p>Why <code>Default</code> for <code>N &gt; 32 </code>is desirable:</p>
<ul>
<li>arrays implement default <span aria-label="tada" class="emoji emoji-1f389" role="img" title="tada">:tada:</span> </li>
<li>consistency with other impls after <a href="https://github.com/rust-lang/rust/issues/74060">#74060</a> lands</li>
<li><code>#[derive(Default)]</code> now works for structs containing arrays.</li>
<li>We can remove <code>ArrayLenAtMost32</code>, resulting in cleaner docs (and potentially minimally better compile perf).</li>
</ul>



<a name="204289932"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204289932" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204289932">(Jul 18 2020 at 07:50)</a>:</h4>
<p>Any thoughts here?</p>



<a name="204294882"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204294882" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mikail Bagishov <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204294882">(Jul 18 2020 at 10:24)</a>:</h4>
<p>I'd like to know more about MaybeUninit optimization problems:<br>
Who is at fault: rustc/llvm?<br>
Is it difficult to fix?<br>
Should we wait until that problem is resolved?</p>



<a name="204295377"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204295377" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204295377">(Jul 18 2020 at 10:42)</a>:</h4>
<p><span class="user-mention silent" data-user-id="119235">David Tolnay</span> opened a issue for this in <a href="https://github.com/rust-lang/rust/issues/74267">#74267</a>.</p>
<blockquote>
<p>Who is at fault: rustc/llvm?</p>
</blockquote>
<p>At least from what I can see this is an issue with llvm which we might be able to circumvent with better mir opts.</p>
<blockquote>
<p>Is it difficult to fix?</p>
</blockquote>
<p>Not completely sure but I would expect that it is not too difficult.</p>
<blockquote>
<p>Should we wait until that problem is resolved?</p>
</blockquote>
<p>I personally don't think so as I highly doubt this will be noticeable.</p>



<a name="204298984"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204298984" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204298984">(Jul 18 2020 at 12:34)</a>:</h4>
<p>I seem to recall seeing that for any usize N, there would be a default for length {N+1}. That avoided the 0 issue because the const of 0 would generate an impl for length 1.</p>



<a name="204298987"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204298987" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204298987">(Jul 18 2020 at 12:35)</a>:</h4>
<p>Am I totally imagining that or was that a suggestion at one point?</p>



<a name="204299111"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204299111" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204299111">(Jul 18 2020 at 12:39)</a>:</h4>
<p>uuuh</p>



<a name="204299150"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204299150" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204299150">(Jul 18 2020 at 12:40)</a>:</h4>
<p>that's really far from working as desired :/</p>



<a name="204299168"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204299168" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204299168">(Jul 18 2020 at 12:40)</a>:</h4>
<p>so it does make sense from a theoretical perspective, but there are quite a lot of reasons why this won't actually work</p>



<a name="204299226"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204299226" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204299226">(Jul 18 2020 at 12:42)</a>:</h4>
<p>ignoring the current <code>ConstEvaluatable</code> restriction, this doesn't enable us to write <code>&lt;[T; N]&gt;::default()</code> because rustc doesn't combine impls</p>



<a name="204299301"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204299301" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204299301">(Jul 18 2020 at 12:45)</a>:</h4>
<p>i.e. we don't allow the following</p>
<div class="codehilite"><pre><span></span><code><span class="k">struct</span> <span class="nc">A</span><span class="o">&lt;</span><span class="k">const</span><span class="w"> </span><span class="n">N</span>: <span class="kt">u8</span><span class="o">&gt;</span><span class="p">;</span><span class="w"></span>
<span class="k">trait</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">fn</span> <span class="nf">foo</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="k">impl</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">A</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">impl</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">A</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="c1">// ...</span>
<span class="k">impl</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">A</span><span class="o">&lt;</span><span class="mi">255</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">fn</span> <span class="nf">test</span><span class="o">&lt;</span><span class="k">const</span><span class="w"> </span><span class="n">N</span>: <span class="kt">u8</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">A</span>::<span class="o">&lt;</span><span class="n">N</span><span class="o">&gt;</span>::<span class="n">foo</span><span class="p">()</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="204299363"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204299363" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204299363">(Jul 18 2020 at 12:47)</a>:</h4>
<p>for</p>
<div class="codehilite"><pre><span></span><code><span class="cp">#![feature(const_generics)]</span><span class="w"></span>
<span class="k">struct</span> <span class="nc">A</span><span class="o">&lt;</span><span class="k">const</span><span class="w"> </span><span class="n">N</span>: <span class="kt">usize</span><span class="o">&gt;</span><span class="p">;</span><span class="w"></span>
<span class="k">trait</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">impl</span><span class="o">&lt;</span><span class="k">const</span><span class="w"> </span><span class="n">N</span>: <span class="kt">usize</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">A</span><span class="o">&lt;</span><span class="p">{</span><span class="n">N</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">}</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
</code></pre></div>


<p>we also get the error</p>
<div class="codehilite"><pre><span></span><code>error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
 --&gt; src/lib.rs:4:12
  |
4 | impl&lt;const N: usize&gt; Foo for A&lt;{N + 1}&gt; {}
  |            ^ unconstrained const parameter

error: aborting due to previous error; 1 warning emitted
</code></pre></div>



<a name="204334382"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204334382" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204334382">(Jul 19 2020 at 05:42)</a>:</h4>
<p>If you could do <code>{N+1}</code>, would that automatically exclude overflow?</p>



<a name="204338202"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204338202" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204338202">(Jul 19 2020 at 07:58)</a>:</h4>
<p>idk, this doesn't really have clear semantics. <code>impl&lt;const N: usize&gt; Foo for A&lt;{N + 1}&gt; {}</code>should probably never work for the same reasons that the following is not possible</p>
<div class="codehilite"><pre><span></span><code><span class="k">trait</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span>: <span class="nb">Iterator</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">T</span>::<span class="n">Item</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
</code></pre></div>


<p>If we have something like <code>impl&lt;const N: usize&gt; Foo&lt;N&gt; for A&lt;{N + 1}&gt; {}</code>, then we would probably get a const eval error when writing<br>
<code>let _: impl Foo&lt;{std::usize::MAX}&gt; = A;</code></p>



<a name="204338215"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204338215" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204338215">(Jul 19 2020 at 07:59)</a>:</h4>
<p>We don't really have a good plan for things like <code>{N + 1}</code> yet, so I can't give you definite answers here</p>



<a name="204370280"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/Default%20for%20arrays%20via%20const%20generics/near/204370280" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/Default.20for.20arrays.20via.20const.20generics.html#204370280">(Jul 19 2020 at 20:51)</a>:</h4>
<p>That's fine – if it's an open question that's a good reason why this shouldn't be supported yet. 🙂</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>